<template>
  <div id="comment-box" class="comment-box" :class="{ mobile: isMobile }">
    <transition name="module" mode="out-in">
      <div v-if="fetching" key="skeleton" class="tools">
        <div class="total-skeleton">
          <skeleton-line class="count-skeleton" />
          <skeleton-line class="like-skeleton" />
        </div>
        <div class="sort-skeleton">
          <skeleton-line />
        </div>
      </div>
      <div v-else key="tools" class="tools">
        <div class="total">
          <div class="count">
            <strong class="count">{{ commentList.pagination.total || 0 }}</strong>
            <span v-text="$i18n.text.comment.count" />
          </div>
          <a v-if="postId !== -1" href class="like" :class="{ liked: isLikedPage }" @click.stop.prevent="likePage">
            <i class="iconfont icon-like" />
            <strong>{{ likes || 0 }}</strong>
            <span v-text="(isMobile && !isEnLang) ? '人喜欢' : $i18n.text.comment.like" />
          </a>
          <a href class="shang" @click.stop.prevent="shang">
            <i class="iconfont icon-shang" />
          </a>
        </div>
        <div class="sort">
          <a
            href
            class="sort-btn"
            :class="{ actived: Object.is(sortMode, constants.SortType.Desc) }"
            @click.stop.prevent="sortComemnts(constants.SortType.Desc)"
            v-text="$i18n.text.comment.new"
          >最新</a>
          <a
            href
            class="sort-btn"
            :class="{ actived: Object.is(sortMode, constants.SortType.Hot) }"
            @click.stop.prevent="sortComemnts(constants.SortType.Hot)"
            v-text="$i18n.text.comment.hot"
          >最热</a>
        </div>
      </div>
    </transition>
    <transition name="module" mode="out-in" @after-enter="loadCommentsAnimateDone">
      <div v-if="isFetching" key="skeleton" class="list-box list-skeleton">
        <ul class="comment-list">
          <li v-for="item in (isMobile ? 3 : 5)" :key="item" class="comment-item">
            <div class="gravatar">
              <skeleton-base />
            </div>
            <div class="content">
              <skeleton-paragraph :lines="4" />
            </div>
          </li>
        </ul>
      </div>
      <div
        v-else-if="!commentList.data.length"
        key="empty"
        class="empty-box"
        v-text="$i18n.text.comment.empty"
      />
      <div v-else key="list" ref="commentList" class="list-box">
        <transition-group name="fade" tag="ul" class="comment-list" @after-enter="addCommentAnimateDone">
          <li
            v-for="comment in commentList.data"
            :id="`comment-item-${comment.id}`"
            :key="comment.id"
            class="comment-item"
          >
            <div v-if="!isMobile" class="cm-avatar">
              <a
                target="_blank"
                rel="external nofollow noopener"
                :href="comment.site"
                @click.stop="clickUser($event, comment)"
              >
                <img
                  :alt="comment.nickname || $i18n.text.comment.anonymous"
                  :src="gravatar(comment.email) || `https://img.luoyuanxiangvip.com/avatar/g.jpg`"
                >
              </a>
            </div>
            <div class="cm-body">
              <div class="cm-header">
                <a
                  class="user-name"
                  target="_blank"
                  rel="external nofollow noopener"
                  :href="comment.site"
                  @click.stop="clickUser($event, comment)"
                >{{ comment.nickname | firstUpperCase }}</a>
                <span v-if="comment.agent" class="os" v-html="osParse(comment.agent)" />
                <span v-if="comment.agent" class="ua" v-html="browserParse(comment.agent)" />
                <span v-if="!isMobile" class="location">
                  <span v-if="comment.province">{{ comment.province }}</span>
                  <span v-if="comment.province && comment.city">&nbsp;-&nbsp;</span>
                  <span>{{ comment.city }}</span>
                </span>
                <span class="flool">#{{ comment.id }}</span>
              </div>
              <div class="cm-content">
                <p v-if="!!comment.pid" class="reply">
                  <span v-text="$i18n.text.comment.reply">回复</span>
                  <span>&nbsp;</span>
                  <a href @click.stop.prevent="toSomeAnchorById(`comment-item-${comment.pid}`)">
                    <span>#{{ comment.pid }}&nbsp;</span>
                    <strong v-if="fondReplyParent(comment.pid)">@{{ fondReplyParent(comment.pid) }}</strong>
                  </a>
                  <span>：</span>
                </p>
                <div v-html="marked(comment.content)" />
              </div>
              <div class="cm-footer">
                <span class="create_at">{{ comment.createTime | timeAgo(language) }}</span>
                <a href class="reply" @click.stop.prevent="replyComment(comment)">
                  <i class="iconfont icon-reply" />
                  <span v-text="$i18n.text.comment.reply">回复</span>
                </a>
                <a
                  href
                  class="like"
                  :class="{ liked: getCommentLiked(comment.id), actived: !!comment.support }"
                  @click.stop.prevent="likeComment(comment)"
                >
                  <i class="iconfont icon-zan" />
                  <span v-text="$i18n.text.comment.ding" />
                  <span>&nbsp;({{ comment.support }})</span>
                </a>
              </div>
            </div>
          </li>
        </transition-group>
      </div>
    </transition>
    <transition name="module">
      <div v-if="!isFetching && commentList.pagination.pages > 1" class="pagination-box">
        <ul v-if="Object.is(sortMode, constants.SortType.Hot)" class="pagination-list">
          <li v-for="(item, index) in commentList.pagination.pages" :key="index" class="item">
            <a
              href
              class="pagination-btn"
              :class="{ 'actived disabled': Object.is(item, commentList.pagination.current) }"
              @click.stop.prevent="Object.is(item, commentList.pagination.current)
                ? false
                : loadComemntList({ page: item })"
            >{{ item }}</a>
          </li>
        </ul>
        <ul v-else class="pagination-list">
          <li class="item">
            <a href class="pagination-btn prev disabled" @click.stop.prevent>
              <span>—</span>
              <span v-text="$i18n.text.comment.pagenation.old">old</span>
            </a>
          </li>
          <li v-for="(item, index) in commentList.pagination.pages" :key="index" class="item">
            <a
              href
              class="pagination-btn"
              :class="{ 'actived disabled': paginationReverseActive(item) }"
              @click.stop.prevent="paginationReverseActive(item)
                ? false
                : loadComemntList({
                  page: commentList.pagination.pages + 1 - item
                })"
            >{{ item }}</a>
          </li>
          <li class="item">
            <a href class="pagination-btn next disabled" @click.stop.prevent>
              <span v-text="$i18n.text.comment.pagenation.new">new</span>
              <span>—</span>
            </a>
          </li>
        </ul>
      </div>
    </transition>
    <form id="post-box" class="post-box" name="comment">
      <!-- 用户编辑部分 -->
      <transition name="module" mode="out-in">
        <div v-if="!userCacheMode || userCacheEditing" key="edit" class="user">
          <div class="name">
            <input
              v-model="user.name"
              required
              type="text"
              name="name"
              autocomplete="on"
              :class="language"
              :placeholder="$i18n.text.comment.profile.name + ' *'"
            >
          </div>
          <div class="email">
            <input
              v-model="user.email"
              required
              type="email"
              name="email"
              autocomplete="on"
              :class="language"
              :placeholder="$i18n.text.comment.profile.email + ' *'"
              @blur="upadteUserGravatar"
            >
          </div>
          <div class="site">
            <input
              v-model="user.site"
              type="url"
              name="url"
              autocomplete="on"
              :class="language"
              :placeholder="$i18n.text.comment.profile.site"
            >
          </div>
          <div v-if="userCacheEditing" class="save">
            <button type="submit" @click="updateUserCache($event)">
              <i class="iconfont icon-success" />
            </button>
          </div>
        </div>
        <!-- 用户设置部分 -->
        <div v-else-if="userCacheMode && !userCacheEditing" key="user" class="user">
          <div class="edit">
            <strong class="name">{{ user.name | firstUpperCase }}</strong>
            <a href class="setting" @click.stop.prevent>
              <i class="iconfont icon-setting" />
              <span class="account-setting" v-text="$i18n.text.comment.setting.account">账户设置</span>
              <ul class="user-tool">
                <li
                  @click.stop.prevent="userCacheEditing = true"
                  v-text="$i18n.text.comment.setting.edit"
                >编辑信息
                </li>
                <li @click.stop.prevent="claerUserCache" v-text="$i18n.text.comment.setting.clear">清空信息</li>
              </ul>
            </a>
          </div>
        </div>
      </transition>
      <div class="editor-box">
        <div class="user">
          <div v-if="!isMobile" class="gravatar">
            <img
              :alt="user.name || $i18n.text.comment.anonymous"
              :src="user.gravatar || `https://img.luoyuanxiangvip.com/avatar/g.jpg`"
            >
          </div>
        </div>
        <div class="editor">
          <transition name="module">
            <div v-if="!!pid" key="reply" class="will-reply">
              <div class="reply-user">
                <span>
                  <span v-text="$i18n.text.comment.reply">回复</span>
                  <span>&nbsp;</span>
                  <a href @click.stop.prevent="toSomeAnchorById(`comment-item-${replyCommentSlef.id}`)">
                    <strong>#{{ replyCommentSlef.id }} @{{ replyCommentSlef.nickname }}：</strong>
                  </a>
                </span>
                <a href class="cancel iconfont icon-cancel" @click.stop.prevent="cancelCommentReply" />
              </div>
              <div class="reply-preview" v-html="marked(replyCommentSlef.content)" />
            </div>
          </transition>
          <div class="markdown">
            <div
              ref="markdown"
              class="markdown-editor"
              contenteditable="true"
              :placeholder="$i18n.text.comment.placeholder"
              @keyup="commentContentChange($event)"
            />
            <div class="markdown-preview" :class="{ actived: previewMode }" v-html="previewContent" />
          </div>
          <div class="editor-tools">
            <a href class="emoji" title="emoji" @click.stop.prevent>
              <i class="iconfont icon-emoji" />
              <div class="emoji-box">
                <ul class="emoji-list">
                  <li
                    v-for="(emoji, index) in emojis"
                    :key="index"
                    class="item"
                    @click="insertEmoji(emoji)"
                    v-text="emoji"
                  />
                </ul>
              </div>
            </a>
            <a href class="image" title="image" @click.stop.prevent="insertContent('image')">
              <i class="iconfont icon-image" />
            </a>
            <a href class="link" title="link" @click.stop.prevent="insertContent('link')">
              <i class="iconfont icon-link-horizontal" />
            </a>
            <a href class="code" title="code" @click.stop.prevent="insertContent('code')">
              <i class="iconfont icon-code-comment" />
            </a>
            <a href class="preview" title="preview" @click.stop.prevent="togglePreviewMode">
              <i class="iconfont icon-eye" />
            </a>
            <button
              type="submit"
              class="submit"
              :disabled="commentPosting || isFetching"
              @click="submitComment($event)"
            >
              <span v-text="commentPosting ? $i18n.text.comment.submiting : $i18n.text.comment.submit" />
            </button>
          </div>
        </div>
      </div>
    </form>
  </div>
</template>

<script>
import lozad from '~/plugins/lozad'
import { mapState } from 'vuex'
import { isBrowser } from '~/environment/esm'
import marked from '~/plugins/marked'
import gravatar from '~/plugins/gravatar'
import { scrollTo } from '~/utils/scroll-to-anywhere'
import { browserParse, osParse } from '~/utils/ua-os-browser'
import { isGuestbookRoute } from '~/utils/route'
import { localHistoryLikes, localUser } from '~/transforms/local-storage'

export default {
  name: 'VueComment',
  props: {
    fetching: {
      type: Boolean,
      default: false
    },
    likes: {
      type: Number,
      default: 0
    },
    postId: {
      type: Number,
      required: true
    }
  },
  data() {
    return {
      lozadObserver: null,
      // 父级评论
      pid: 0,
      // 评论排序
      sortMode: -1,
      // 编辑器相关
      comemntContentHtml: '',
      comemntContentText: '',
      previewContent: '',
      previewMode: false,
      // 用户相关
      userCacheMode: false,
      userCacheEditing: false,
      user: {
        name: '',
        email: '',
        site: '',
        gravatar: null
      },
      // 用户历史数据
      historyLikes: {
        pages: [],
        comments: []
      },
      regexs: {
        email: /\w[-\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{2,14}/,
        url: /^((https|http):\/\/)+[A-Za-z0-9]+\.[A-Za-z0-9]+[\/=\?%\-&_~`@[\]\':+!]*([^<>\"\"])*$/
      },
      emojis: ['😃', '😂', '😅', '😉', '😌', '😔', '😓', '😢', '😍', '😘', '😜', '😡', '😤', '😭', '😱', '😳', '😵', '🌚', '🙏', '👆', '👇', '👌', '🤘', '👍', '👎', '💪', '👏', '🌻', '🌹', '💊', '🇨🇳', '🇺🇸', '🇯🇵 ', '🚩', '🐶', '❤️', '💔', '💩', '👻']
    }
  },
  computed: {
    ...mapState({
      commentList: state => state.comment.data,
      commentFetching: state => state.comment.fetching,
      commentPosting: state => state.comment.posting,
      constants: state => state.global.constants,
      language: state => state.global.language,
      isMobile: state => state.global.isMobile,
      config: state => state.global.adminInfo,
      blacklist: state => state.global.appOption.data
    }),
    isFetching() {
      // 1. 宿主组件还在加载时，列表和 tool 都呈加载状态
      // 2. 宿主组件加载完成，如果自己还在请求，则列表呈加载状态
      // 3. 自己已请求完，宿主组件还在加载，列表和 tool 都呈加载状态
      return this.fetching || this.commentFetching
    },
    isEnLang() {
      return this.$store.getters['global/isEnLang']
    },
    isLikedPage() {
      return this.historyLikes.pages.includes(this.postId)
    },
    isArticlePage() {
      return this.$route.params.article_id
    },
    isGuestbookPage() {
      return isGuestbookRoute(this.$route.name)
    },
    replyCommentSlef() {
      return this.commentList.data.find(comment => Object.is(comment.id, this.pid))
    }
  },
  mounted() {
    this.initAppOptionBlackList()
    if (isBrowser) {
      this.observeLozad()
    }
  },
  activated() {
    this.initUser()
    // 1. 组件不再负责初始加载评论列表数据的职责
    // 2. 组件仅负责初评论列表数据翻页、排序的职责
    // 3. 当容器组件还在请求时，组件全量 Loading
    // 4. 当只有评论列表在请求时，列表单独 Loading
  },
  destroyed() {
    this.$store.commit('comment/clearListData')
  },
  deactivated() {
    this.lozadObserver = null
    this.$store.commit('comment/clearListData')
  },
  methods: {
    browserParse,
    osParse,
    // 初始化本地用户即本地用户的点赞历史
    initUser() {
      const user = localUser.get()
      const historyLikes = localHistoryLikes.get()
      historyLikes && (this.historyLikes = historyLikes)
      if (user) {
        this.user = user
        this.upadteUserGravatar()
        this.userCacheMode = true
      }
    },
    loadCommentsAnimateDone() {
      this.observeLozad()
    },
    addCommentAnimateDone() {
      this.observeLozad()
    },
    observeLozad() {
      const listElement = this.$refs.commentList
      const lozadElements = listElement && listElement.querySelectorAll('.lozad')
      if (!lozadElements || !lozadElements.length) {
        return false
      }
      this.lozadObserver = lozad(lozadElements, {
        loaded: element => element.classList.add('loaded')
      })
      this.lozadObserver.observe()
    },
    // 初始化黑名单
    initAppOptionBlackList() {
      this.$store.dispatch('global/fetchAppOption')
    },
    shang() {
      this.$ga.event('内容赞赏', '点击', 'tool')
      window.utils.openImgPopup(`https://img.luoyuanxiangvip.com/appreciation/wx_zfb_code.jpg`, 'shang')
    },
    // markdown解析服务
    marked(content) {
      return marked(content, null, false)
    },
    // 头像服务
    gravatar(email) {
      if (!this.regexs.email.test(email)) {
        return null
      } else {
        if (email === this.config.authorEmail) {
          return this.config.authorAvatar
        }
        return gravatar.url(email, {
          protocol: 'https'
        })
      }
    },
    // 更新用户数据
    updateUserCache(event) {
      event.preventDefault()
      if (!this.user.name) {
        return alert(this.$i18n.text.comment.profile.name + '?')
      }
      if (!this.user.email) {
        return alert(this.$i18n.text.comment.profile.email + '?')
      }
      if (!this.regexs.email.test(this.user.email)) {
        return alert(this.$i18n.text.comment.profile.emailerr)
      }
      if (this.user.site && !this.regexs.url.test(this.user.site)) {
        return alert(this.$i18n.text.comment.profile.siteerr)
      }
      localUser.set(this.user)
      this.userCacheEditing = false
    },
    // 清空用户数据
    claerUserCache() {
      this.userCacheMode = false
      this.userCacheEditing = false
      localUser.remove()
      Object.keys(this.user).forEach(key => {
        this.user[key] = ''
      })
    },
    // 更新当前用户头像
    upadteUserGravatar() {
      const emailIsVerified = this.regexs.email.test(this.user.email)
      this.user.gravatar = emailIsVerified ? this.gravatar(this.user.email) : null
    },
    // 编辑器相关
    commentContentChange() {
      const html = this.$refs.markdown.innerHTML
      const text = this.$refs.markdown.innerText
      if (!Object.is(html, this.comemntContentHtml)) {
        this.comemntContentHtml = html
      }
      if (!Object.is(text, this.comemntContentText)) {
        this.comemntContentText = text
      }
    },
    updateCommentContent({ start = '', end = '' }) {
      if (!start && !end) return false
      // 如果选中了内容，则把选中的内容替换，否则在光标位置插入新内容
      const selectedText = (window.getSelection || document.getSelection)().toString()
      const currentText = this.$refs.markdown.innerText
      if (selectedText) {
        this.$refs.markdown.innerText = currentText.replace(selectedText, start + selectedText + end)
      } else {
        this.$refs.markdown.innerText = this.$refs.markdown.innerText += (start + end)
        this.$refs.markdown.scrollTop = this.$refs.markdown.scrollHeight
      }
      this.commentContentChange()
    },
    clearCommentContent(content) {
      this.comemntContentHtml = ''
      this.$refs.markdown.innerHTML = this.comemntContentHtml
      this.commentContentChange()
    },
    insertContent(type) {
      const contents = {
        image: {
          start: `![`,
          end: `](https://)`
        },
        link: {
          start: `[`,
          end: `](https://)`
        },
        code: {
          start: '\n```javascript\n',
          end: '\n```'
        }
      }
      this.updateCommentContent(contents[type])
    },
    insertEmoji(emoji) {
      this.updateCommentContent({ end: emoji })
    },
    // 切换预览模式
    togglePreviewMode() {
      this.previewContent = this.marked(this.comemntContentText)
      this.previewMode = !this.previewMode
    },
    // 评论排序
    sortComemnts(sort) {
      if (this.sortMode !== sort) {
        this.sortMode = sort
        this.loadComemntList()
      }
    },
    // 翻页反向计算
    paginationReverseActive(index) {
      const pagination = this.commentList.pagination
      // pagination.total_page + 1 - pagination.current_page
      return Object.is(index, pagination.pages + 1 - pagination.current)
    },
    // 点击用户
    clickUser(event, user) {
      if (!user.site) event.preventDefault()
    },
    // 跳转到某条指定的id位置
    toSomeAnchorById(id) {
      const targetDom = document.getElementById(id)
      if (targetDom) {
        const isToEditor = Object.is(id, 'post-box')
        scrollTo(targetDom, 200, { offset: isToEditor ? 0 : -300 })
        // 如果是进入编辑模式，则需要激活光标
        if (isToEditor) {
          const p = this.$refs.markdown
          const s = window.getSelection()
          const r = document.createRange()
          r.setStart(p, p.childElementCount)
          r.setEnd(p, p.childElementCount)
          s.removeAllRanges()
          s.addRange(r)
        }
      }
    },
    // 回复评论
    replyComment(comment) {
      this.pid = comment.id
      this.toSomeAnchorById('post-box')
    },
    // 取消回复
    cancelCommentReply() {
      this.pid = 0
    },
    // 找到回复来源
    fondReplyParent(comment_id) {
      const parent = this.commentList.data.find(comment => Object.is(comment.id, comment_id))
      return parent ? parent.nickname : null
    },
    // 喜欢当前页面
    likePage() {
      if (this.isLikedPage) {
        return false
      }
      this.$store.dispatch(
        this.postId === this.constants.CommentPostType.Guestbook
          ? 'global/fetchLikeSite'
          : 'article/fetchLikeArticle',
        this.postId
      )
        .then(data => {
          this.historyLikes.pages.push(this.postId)
          localHistoryLikes.set(this.historyLikes)
        })
        .catch(err => {
          console.warn('喜欢失败', err)
          alert(this.$i18n.text.comment.profile.actionerr)
        })
    },
    // 点赞某条评论
    likeComment(comment) {
      if (this.getCommentLiked(comment.id)) {
        return false
      }
      this.$store.dispatch('comment/fetchLikeComment', comment)
        .then(() => {
          this.historyLikes.comments.push(comment.id)
          localHistoryLikes.set(this.historyLikes)
        })
        .catch(error => {
          console.warn('评论点赞失败', error)
          alert(this.$i18n.text.comment.profile.actionerr)
        })
    },
    // 获取某条评论是否被点赞
    getCommentLiked(comment_id) {
      return this.historyLikes.comments.includes(comment_id)
    },
    // 获取评论列表
    loadComemntList(params = {}) {
      params.sort = this.sortMode
      this.$store.dispatch('comment/fetchList', Object.assign(params, { post_id: this.postId }))
    },
    // 提交评论
    submitComment(event) {
      // 为了使用原生表单拦截，不使用事件修饰符
      event.preventDefault()
      if (!this.user.name) {
        return alert(this.$i18n.text.comment.profile.name + '?')
      }
      if (!this.user.email) {
        return alert(this.$i18n.text.comment.profile.email + '?')
      }
      if (!this.regexs.email.test(this.user.email)) {
        return alert(this.$i18n.text.comment.profile.emailerr)
      }
      if (this.user.site && !this.regexs.url.test(this.user.site)) {
        return alert(this.$i18n.text.comment.profile.siteerr)
      }
      if (!this.comemntContentText || !this.comemntContentText.replace(/\s/g, '')) {
        return alert(this.$i18n.text.comment.profile.content + '?')
      }
      const lineOverflow = this.comemntContentText.split('\n').length > 36
      const lengthOverflow = this.comemntContentText.length > 2000
      if (lineOverflow || lengthOverflow) {
        return alert(this.$i18n.text.comment.profile.contenterr)
      }
      // 使用服务单配置的黑名单在本地校验邮箱和关键字
      if (this.blacklist.mails.includes(this.user.email) ||
          (this.blacklist.keywords.length &&
            eval(`/${this.blacklist.keywords.join('|')}/ig`).test(this.comemntContentText))) {
        alert(this.$i18n.text.comment.profile.submiterr)
        console.warn('评论发布失败\n1：被 Akismet 过滤\n2：邮箱/IP 被列入黑名单\n3：内容包含黑名单关键词')
        return false
      }
      if (!this.user.site) {
        Reflect.deleteProperty(this.user, 'site')
      }
      this.$store.dispatch('comment/fetchPostComment', {
        pid: this.pid,
        postId: this.postId,
        nickname: this.user.name,
        avatar: this.user.gravatar,
        email: this.user.email,
        site: this.user.site,
        content: this.comemntContentText,
        agent: navigator.userAgent
      }).then(data => {
        // 发布成功后清空评论框内容并更新本地信息
        const content = data.result.content
        const emoji233333 = this.$root.$emoji233333
        if (emoji233333 && emoji233333.launch) {
          // 为表情做一次缓冲
          const preImage = (url, callback) => {
            const img = new Image()
            img.src = url
            if (img.complete) return callback(img)
            img.onload = () => callback(img)
          }
          if (content.includes('2333') || content.includes('哈哈')) {
            const emoji = emoji233333.defaultEmoji
            emoji233333.update({
              emoji,
              speed: 12,
              staggered: true,
              increaseSpeed: 0.4
            })
            preImage(emoji, emoji233333.launch.bind(emoji233333))
          } else if (content.includes('666')) {
            const emoji = '/images/emojis/666.png'
            emoji233333.update({
              emoji,
              speed: 12,
              staggered: true,
              increaseSpeed: 0.4
            })
            preImage(emoji, emoji233333.launch.bind(emoji233333))
          } else if (content.includes('呵呵')) {
            const emoji = '/images/emojis/hehe.png'
            emoji233333.update({ emoji, staggered: false, speed: 8, increaseSpeed: 0.04 })
            preImage(emoji, emoji233333.launch.bind(emoji233333))
          }
        }
        this.previewMode = false
        this.userCacheMode = true
        this.cancelCommentReply()
        this.clearCommentContent()
        localUser.set(this.user)
      }).catch(error => {
        console.warn('评论发布失败，可能原因：被 Akismet 过滤，或者：\n', error)
        alert(this.$i18n.text.comment.profile.submiterr)
      })
    }
  }
}
</script>

<style lang="scss">
  .cm-content,
  .reply-preview,
  .markdown-preview {
    font-size: 1em;
    line-height: 2em;
    margin: .5em 0;
    word-wrap: break-word;

    a {
      text-decoration: underline;
    }

    img {
      margin: .5rem 0;
      max-width: 100%;
      border-radius: 2px;
      cursor: pointer;
    }

    p {
      margin: 0;
    }

    code {
      color: #bd4147;
      padding: .3em .5em;
      margin: 0 .5em;
      border-radius: $radius;
      background-color: $module-hover-bg;
    }

    pre {
      display: flex;
      align-items: baseline;
      flex-wrap: wrap-reverse;
      position: relative;
      overflow: hidden;
      margin-top: .6em;
      margin-bottom: 1em;
      padding-top: 2.5em;
      border-radius: $radius;
      background-color: rgba(0, 0, 0, 0.8);

      &:before {
        color: white;
        content: attr(data-lang) " CODE";
        height: 2.5em;
        line-height: 2.5em;
        font-size: 1em;
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        font-weight: 700;
        background-color: rgba(68, 68, 68, 0.9);
        display: block;
        text-transform: uppercase;
        text-align: center;
      }

      > .code-lines {
        display: none;
      }

      > code {
        margin: 0;
        padding: 1em;
        float: left;
        width: 100%;
        height: 100%;
        display: block;
        line-height: 1.6em;
        color: rgba(255, 255, 255, 0.87);
        background-color: transparent;
      }
    }
  }

  #comment-box {
    background-color: $module-bg;
    padding: 1em;

    &.mobile {

      > .list-box {

        > .comment-list {

          > .comment-item {
            padding: 0;
            margin-bottom: 1rem;

            > .cm-body {
              padding: .6em;
            }
          }
        }
      }

      > .post-box {

        > .user {
          padding: 0;
          height: auto;
          flex-direction: column;

          > .name,
          > .email,
          > .site,
          > .save {
            width: 80%;
            margin-left: 0;
            margin-right: 0;
            margin-bottom: 1rem;
          }

          > .save {
            width: 30%;
            margin-bottom: 0;
          }
        }

        > .editor-box {

          > .user {
            margin: 0;
          }
        }
      }
    }

    > .tools {
      display: flex;
      padding: 1em 0;
      padding-top: 0;
      align-items: center;
      justify-content: space-between;
      border-bottom: 1px solid $module-hover-bg;
      margin-bottom: .6em;

      .count-skeleton,
      .like-skeleton,
      .sort-skeleton {
        height: 2rem;
      }

      .total-skeleton {
        display: flex;
        width: 70%;

        .count-skeleton {
          width: 20%;
          margin-right: 1rem;
        }

        .like-skeleton {
          width: 40%;
        }
      }

      .sort-skeleton {
        width: 20%;
      }

      > .total {
        display: flex;
        font-size: 1em;

        > .like,
        > .shang,
        > .count {
          padding: .2em .5em;
          background-color: $module-hover-bg;
        }

        @keyframes shangBtnBg {
          0% {
            background: $primary-opacity-9;
          }
          50% {
            background: rgba($accent, .8);
          }
          100% {
            background: $primary-opacity-9;
          }
        }

        > .shang {
          margin-left: .5em;
          color: white;
          animation: shangBtnBg 1s infinite;
        }

        > .like {
          margin-left: .5em;

          > .iconfont {
            margin-right: .5rem;
          }

          &:hover {
            background-color: $module-hover-bg-darken-20;
          }

          &.liked {

            > .iconfont {
              color: $red;
            }
          }
        }
      }

      > .sort {

        > .sort-btn {
          margin-left: 1em;

          &.actived {
            color: $black;
            font-weight: bold;
          }
        }
      }
    }

    > .list-skeleton {

      .comment-item {
        padding-left: 0 !important;
        display: flex;
        justify-content: space-around;
        align-items: center;

        .gravatar {
          width: 5rem;
          height: 5rem;
        }

        .content {
          width: calc((100% - 5rem) * 0.9);
        }
      }
    }

    > .empty-box {
      font-weight: bold;
      text-align: center;
      height: 5rem;
      line-height: 5rem;
    }

    > .list-box {

      > .comment-list {
        padding: 0;
        margin: 0;
        list-style-type: none;

        > .comment-item {
          position: relative;
          padding: .6em 0 .6em 1.5em;

          &:hover {

            > .cm-avatar {

              > a {
                > img {
                  transition: transform .5s ease-out;
                  transform: rotate(360deg);
                }
              }
            }

            > .cm-body {
              background-color: $module-hover-bg-darken-20;
            }
          }

          > .cm-avatar {
            display: block;
            position: absolute;
            left: 0;
            top: 2em;
            background-color: $module-hover-bg;

            > a {
              display: block;
              border: .3em solid $module-bg;
              width: 4em;
              height: 4em;

              > img {
                width: 100%;
                height: 100%;
                transition: transform .5s ease-out;
              }
            }
          }

          > .cm-body {
            display: block;
            width: 100%;
            height: 100%;
            padding: .6em .6em .6em 3.2em;
            background-color: $module-hover-bg;

            > .cm-header {
              display: block;
              position: relative;

              > .user-name {
                font-weight: bold;
                margin-right: .8em;
                // font-family: Microsoft YaHei,Arial,Helvetica,sans-serif;

                &:hover {
                  text-decoration: underline;
                }
              }

              > .os,
              > .ua,
              > .location {
                color: $disabled;
                font-size: .8em;
                margin-right: .8em;

                .iconfont {
                  margin-right: .2em;
                }
              }

              > .flool {
                color: $dividers;
                font-weight: 900;
                font-size: .8em;
                display: inline-block;
                line-height: 2rem;
                float: right;
              }
            }

            > .cm-content {
              font-size: .95em;

              > .reply {
                color: $disabled;
                font-weight: bold;

                > a {
                  text-decoration: none;
                }
              }
            }

            > .cm-footer {
              display: flex;

              > .create_at,
              > .reply,
              > .like {
                font-size: .8em;
                margin-right: 1em;
              }

              > .create_at {
                color: $disabled;
              }

              > .like {

                &:hover {
                  color: $red;
                }

                &.liked {
                  color: $red;
                  font-weight: bold;
                }

                &.actived {
                  font-weight: bold;

                  &:hover {
                    color: $red;
                  }
                }
              }

              > .reply,
              > .like {
                opacity: .8;

                > .iconfont {
                  opacity: .8;
                  margin-right: .2em;
                }

                &:hover {
                  opacity: 1;
                }
              }
            }
          }
        }
      }
    }

    > .pagination-box {
      margin-top: .5rem;

      > .pagination-list {
        margin: 0;
        padding: 0;
        display: flex;
        justify-content: center;
        list-style-type: none;

        > .item {
          margin: 0 0.5em;

          > .pagination-btn {
            display: inline-block;
            width: 2rem;
            height: 2rem;
            display: inline-block;
            line-height: 2rem;
            text-align: center;

            &.prev,
            &.next {
              width: 5em;
              font-size: .9em;

              &:hover {
                background: none;
              }
            }

            &.disabled {
              cursor: no-drop;
              opacity: .5;
            }

            &.actived,
            &:hover {
              background-color: $module-hover-bg;
            }
          }
        }
      }
    }

    > .post-box {
      display: block;
      border-top: 1px dashed $module-hover-bg-darken-20;
      margin-top: 1rem;
      padding-top: 1rem;

      > .user {
        width: 100%;
        height: 2em;
        line-height: 2em;
        display: flex;
        margin-bottom: 1rem;
        padding-left: 5.2rem;

        > .edit {
          flex-grow: 1;
          text-align: right;
          line-height: 2em;
          position: relative;

          > .name {
            // font-family: DINRegular, -apple-system, Microsoft YaHei, Arial, Helvetica, sans-serif;
          }

          > .setting {
            font-size: 1rem;
            margin-left: 1rem;
            display: inline-block;
            position: relative;

            &:hover {

              > .user-tool {
                display: block;
              }
            }

            > .iconfont {
              margin-right: .5rem;
            }

            > .account-setting {
              text-transform: capitalize;
            }

            > .user-tool {
              display: none;
              position: absolute;
              right: 0;
              top: 2em;
              margin: 0;
              padding: 0;
              padding-top: .5rem;
              list-style-type: square;
              z-index: 99;
              color: $white;

              > li {
                padding: 0 1rem;
                background-color: rgba(green, 0.5);
              }

              > li:hover {
                background-color: rgba(green, 0.8);
              }
            }
          }
        }

        > .save {
          width: 10%;
          margin-left: 1em;
          flex-grow: 1;
          line-height: 2em;
          text-align: center;
          // font-family: Microsoft YaHei,Arial,Helvetica,sans-serif;

          > button {
            display: block;
            width: 100%;
            background-color: $module-hover-bg;

            &:hover {
              background-color: $module-hover-bg-darken-10;
            }
          }
        }

        > .name,
        > .email,
        > .site {
          // font-family: Microsoft YaHei,Arial,Helvetica,sans-serif;
          flex-grow: 1;

          > input {
            width: 100%;
            height: 2em;
            background-color: $module-hover-bg;

            &:focus,
            &:hover {
              background-color: $module-hover-bg-darken-10;
            }
          }
        }

        > .name,
        > .email {
          margin-right: 1em;
        }
      }

      > .editor-box {
        width: 100%;
        display: flex;

        > .user {
          margin-right: 1em;

          > .gravatar {
            display: block;
            margin-bottom: .5em;
            width: 4rem;
            height: 4rem;
            background-color: $module-hover-bg-darken-20;

            > img {
              width: 100%;
              height: 100%;
              transition: transform .5s ease-out;
            }
          }
        }

        > .editor {
          flex-grow: 1;
          position: relative;
          overflow: hidden;

          > .will-reply {
            font-size: .95em;
            margin-bottom: 1em;

            > .reply-user {
              display: flex;
              justify-content: space-between;
              margin-bottom: 1rem;
              padding: 0 1rem;
              height: 2.6em;
              line-height: 2.6em;
              background-color: $module-hover-bg;

              &:hover {
                background-color: $module-hover-bg-darken-10;
              }
            }

            > .reply-preview {
              max-height: 10em;
              overflow: auto;
              padding: 1rem;

              background-color: $module-hover-bg;

              &:hover {
                background-color: $module-hover-bg-darken-10;
              }
            }
          }

          > .markdown {
            position: relative;
            overflow: hidden;

            > .markdown-editor {
              min-height: 6em;
              max-height: 36em;
              overflow: auto;
              outline: none;
              padding: .5em;
              cursor: auto;
              font-size: .95em;
              line-height: 1.8em;
              background-color: $module-hover-bg;

              &:empty:before {
                content: attr(placeholder);
                color: $disabled;
              }

              &:focus {
                content: none;
              }

              &:hover {
                background-color: $module-hover-bg-darken-10;
              }
            }

            > .markdown-preview {
              position: absolute;
              top: 0;
              left: 0;
              width: 100%;
              height: 0;
              overflow: auto;
              margin: 0;
              padding: .5em;
              @include css3-prefix(transform, translateY(-100%));
              background-color: rgba(235, 235, 235, 0.85);
              transition: transform .2s;

              &.actived {
                height: 100%;
                transition: transform .2s;
                @include css3-prefix(transform, translateY(0));
              }
            }
          }

          > .editor-tools {
            height: 2em;
            line-height: 2em;
            background-color: $module-hover-bg-opacity-9;

            > .emoji {

              > .emoji-box {
                display: none;
                position: absolute;
                bottom: 2em;
                left: 0;
                background-color: $module-bg;

                > .emoji-list {
                  list-style: none;
                  padding: 0;
                  margin: 0;
                  font-size: 1.3em;
                  display: flex;
                  flex-wrap: wrap;

                  > .item {
                    padding: 0 .4em;
                    cursor: pointer;

                    &:hover {
                      background-color: $module-hover-bg;
                    }
                  }
                }
              }

              &:hover {
                > .emoji-box {
                  display: block;
                }
              }
            }

            > .emoji,
            > .image,
            > .link,
            > .code,
            > .preview {
              width: 2em;
              height: 2em;
              text-align: center;
              display: inline-block;

              &:hover {
                background-color: $module-hover-bg-darken-20;
              }
            }

            > .submit {
              float: right;
              width: 7em;
              background-color: $module-hover-bg-darken-20;

              &:hover {
                background-color: $module-hover-bg-darken-40;
              }
            }
          }
        }
      }
    }
  }
</style>
